package com.symaster.common.geom;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import com.symaster.common.geom.canvas.listener.CanvasKeyListener;
import com.symaster.common.geom.canvas.listener.CanvasMouseListener;
import com.symaster.common.geom.canvas.listener.CanvasMouseMotionListener;
import com.symaster.common.geom.entity.Point;
import com.symaster.common.geom.entity.Polygon;
import com.symaster.common.geom.entity.*;
import com.symaster.common.geom.util.PointUtil;
import com.symaster.common.image.util.ImageUtil;
import com.symaster.common.swing.util.SwingUtil;
import com.symaster.common.thread.WatchThread;
import com.symaster.common.util.CommonUtil;
import com.symaster.common.util.IOUtil;
import org.apache.commons.lang3.StringUtils;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.Closeable;
import java.util.List;
import java.util.*;
import java.util.Map;
import java.util.stream.Collectors;

public class PolygonOffsetEditing<T extends Node> extends JComponent implements Closeable {

    private JPanel content_pane;
    private JScrollPane root_scroll_panel;
    private JButton auto_move_button;
    private JButton re_layout_button;
    private JCheckBox enable_cavity_check_box;
    private JTextField x_input;
    private JTextField y_input;
    private JComboBox<String> unitOverload;
    private JLabel node_x_text;
    private JLabel node_y_text;
    private JLabel node_width_text;
    private JLabel node_height_text;
    private JLabel node_point_text;
    private JTextField angle_input;
    private JCheckBox reset_point_check_box;
    private JLabel id_text;
    private JLabel other_message_text;
    private JLabel similarity_text;
    private JButton check_select_button;
    private JButton check_move_button;
    private JButton check_zoom_button;
    private JButton check_rotate_button;
    private JButton auto_layout_button;
    private JButton auto_layout_config_button;
    private Canvas canvas;
    private final ShapeSpace<T> shapeSpace;
    private final Map<Integer, T> polygonMap;
    private final Map<Integer, Point> pointMap;
    private final int w;
    private final int h;
    private final Watch watch;
    private Set<CopyListener<T>> copyListener;

    public PolygonOffsetEditing(int w, int h) {
        double allScale = 0.15;
        this.w = (int) (w * allScale);
        this.h = (int) (h * allScale);

        shapeSpace = new ShapeSpace<>(w, h, allScale);
        polygonMap = new HashMap<>();
        pointMap = new HashMap<>();
        initPage();
        initListener();
        this.watch = new Watch(this);
        this.watch.start();
    }

    public void addCopyListener(CopyListener<T> listener) {
        if (copyListener == null) {
            copyListener = new HashSet<>();
        }
        copyListener.add(listener);
    }

    public void removeCopyListener(CopyListener<T> listener) {
        if (copyListener == null) {
            return;
        }
        copyListener.remove(listener);
    }

    public void clearCopyListener() {
        if (copyListener == null) {
            return;
        }
        copyListener.clear();
    }

    private void initListener() {
        this.auto_move_button.addActionListener(e -> {
            List<PolygonComponent<?>> selectList = this.canvas.getSelectList();
            if (selectList == null || selectList.size() == 0) {
                return;
            }

            if (selectList.size() > 2) {
                int i = selectList.size() - 2;
                for (int im = 0; im < i; im++) {
                    int i1 = 0;
                    int i2 = 0;
                    while (i1 == i2) {
                        i1 = new Random().nextInt(selectList.size());
                        i2 = new Random().nextInt(selectList.size());
                    }
                    PolygonComponent<?> cache = selectList.get(i1);
                    PolygonComponent<?> c2 = selectList.get(i2);
                    selectList.set(i2, cache);
                    selectList.set(i1, c2);
                }
            }

            List<T> list = new LinkedList<>();
            Map<T, PolygonComponent<?>> map = new HashMap<>();
            for (PolygonComponent<?> polygonComponent : selectList) {
                T remove = shapeSpace.remove(polygonComponent.getSrc().getId());
                list.add(remove);
                map.put(remove, polygonComponent);
            }

            for (T k : list) {
                PolygonComponent<?> v = map.get(k);
                shapeSpace.add(k, false);
                if (reset_point_check_box.isSelected()) {
                    shapeSpace.initMovePoint(k.getId());
                }
                if (enable_cavity_check_box.isSelected()) {
                    shapeSpace.cavityAutoLayout(k.getId());
                } else {
                    shapeSpace.autoLayout(k.getId());
                }
                T t = shapeSpace.myFindNode(k.getId());
                v.setLocation((int) t.getX(), (int) t.getY());
                v.setLastPoint(v.getLocation());
            }

            showErrorBorder();
        });
        this.re_layout_button.addActionListener(e -> {
            this.canvas.selectAll();
            this.auto_move_button.setEnabled(true);
            this.auto_move_button.doClick();
        });
        unitOverload.addActionListener(e -> showPoint());
        x_input.registerKeyboardAction(this::xInput, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        y_input.registerKeyboardAction(this::yInput, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        angle_input.registerKeyboardAction(this::angleInput, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        canvas.addCopyListener(new com.symaster.common.swing.listener.CopyListener() {
            @Override
            public void copy() {
                copyListener();
            }

            @Override
            public void paste() {
                pasteListener();
            }
        });
        canvas.addShowMenuListener(popupMenu -> {

            List<PolygonComponent<?>> selectList = canvas.getSelectList();
            if (selectList.size() == 0) {
                return;
            }

            JMenuItem item2 = new JMenuItem("复制");
            item2.addActionListener(e -> copyListener());
            popupMenu.add(item2);

            if (selectList.size() == 1) {
                JMenuItem item = new JMenuItem("编辑坐标信息");
                PolygonComponent<?> polygonComponent = selectList.get(0);
                item.addActionListener(e -> {
                    T node = shapeSpace.findNode(polygonComponent.getSrc().getId());
                    PolygonPointEditing polygonPointEditing = new PolygonPointEditing(node.getPolygon());
                    JDialog jDialog = new JDialog();
                    jDialog.setContentPane(polygonPointEditing);
                    jDialog.setPreferredSize(new Dimension(1620, 940));
                    jDialog.pack();
                    SwingUtil.toCenter(jDialog);

                    // polygonPointEditing.draw(node.getPolygon());
                    jDialog.setVisible(true);

                });
                popupMenu.add(item);
            }
        });
    }

    public void copyListener() {
        List<PolygonComponent<?>> selectList = canvas.getSelectList();
        if (selectList.size() == 0) {
            return;
        }

        if (copyListener == null) {
            return;
        }
        List<T> collect = selectList.stream().map(e -> getElement(e.getSrc().getId())).collect(Collectors.toList());
        copyListener.forEach(e -> e.copy(collect));
    }

    public void pasteListener() {
        if (copyListener == null) {
            return;
        }
        copyListener.forEach(CopyListener::paste);
    }

    private void angleInput(ActionEvent actionEvent) {
        if (StringUtils.isEmpty(angle_input.getText())) {
            return;
        }
        double input;
        try {
            input = Double.parseDouble(angle_input.getText());
        } catch (NumberFormatException e) {
            return;
        }
        List<PolygonComponent<?>> selectList = canvas.getSelectList();
        for (PolygonComponent<?> polygonComponent : selectList) {
            Integer id = polygonComponent.getSrc().getId();
            rotate(id, input);
        }
    }

    private void yInput(ActionEvent actionEvent) {
        if (StringUtils.isEmpty(y_input.getText())) {
            return;
        }
        double input;
        try {
            input = formatUnity(Double.parseDouble(y_input.getText())) * shapeSpace.getAllScale();
        } catch (NumberFormatException e) {
            return;
        }

        List<PolygonComponent<?>> selectList = canvas.getSelectList();
        if (selectList.size() == 1) {
            PolygonComponent<?> polygonComponent = selectList.get(0);
            Integer id = polygonComponent.getSrc().getId();
            shapeSpace.moveY(id, input);
            T t = shapeSpace.myFindNode(id);
            polygonComponent.setLocation((int) t.getX(), (int) t.getY());
            polygonComponent.setLastPoint(polygonComponent.getLocation());
        }
        if (selectList.size() > 1) {
            for (PolygonComponent<?> polygonComponent : selectList) {
                Integer id = polygonComponent.getSrc().getId();
                shapeSpace.translateY(id, input);
                T t = shapeSpace.myFindNode(id);
                polygonComponent.setLocation((int) t.getX(), (int) t.getY());
                polygonComponent.setLastPoint(polygonComponent.getLocation());
            }
            y_input.setText("0");
        }
        if (selectList.size() > 0) {
            canvasMouseReleased();
        }
    }

    private void xInput(ActionEvent actionEvent) {
        if (StringUtils.isEmpty(this.x_input.getText())) {
            return;
        }
        double input;
        try {
            input = formatUnity(Double.parseDouble(this.x_input.getText())) * this.shapeSpace.getAllScale();
        } catch (NumberFormatException e) {
            return;
        }

        List<PolygonComponent<?>> selectList = this.canvas.getSelectList();
        if (selectList.size() == 1) {
            PolygonComponent<?> polygonComponent = selectList.get(0);
            Integer id = polygonComponent.getSrc().getId();
            this.shapeSpace.moveX(id, input);
            T t = this.shapeSpace.myFindNode(id);
            polygonComponent.setLocation((int) t.getX(), (int) t.getY());
            polygonComponent.setLastPoint(polygonComponent.getLocation());
        }
        if (selectList.size() > 1) {
            for (PolygonComponent<?> polygonComponent : selectList) {
                Integer id = polygonComponent.getSrc().getId();
                this.shapeSpace.translateX(id, input);
                T t = this.shapeSpace.myFindNode(id);
                polygonComponent.setLocation((int) t.getX(), (int) t.getY());
                polygonComponent.setLastPoint(polygonComponent.getLocation());
            }
            this.y_input.setText("0");
        }
        if (selectList.size() > 0) {
            canvasMouseReleased();
        }
    }

    public double formatUnity(double value) {
        String unit = (String) unitOverload.getSelectedItem();
        if ("mm".equals(unit)) {
            return value * 120 / 25.4;
        }
        return value;
    }

    public double parseUnity(double value) {
        String unit = (String) unitOverload.getSelectedItem();
        if ("mm".equals(unit)) {
            return value / 120 * 25.4;
        }
        return value;
    }

    private void initPage() {
        this.setLayout(new BorderLayout());
        this.add(content_pane);
        this.unitOverload.addItem("px");
        this.unitOverload.addItem("mm");
        this.canvas = new Canvas(w, h);
        this.canvas.setPreferredSize(new Dimension(w, h));
        this.canvas.setBackground(new Color(123, 123, 123));
        this.canvas.addKeyListener(new CanvasKeyListener(this.canvas));
        this.canvas.addMouseListener(new CanvasMouseListener(this.canvas));
        this.canvas.addMouseMotionListener(new CanvasMouseMotionListener(this.canvas));
        this.canvas.setFocusable(true);
        this.canvas.addCanvasMouseListener(this::canvasMouseReleased);

        this.check_select_button.setIcon(SwingUtil.loadIconEnabledCache("geom/select-b.png", 15, 15));
        this.check_move_button.setIcon(SwingUtil.loadIconEnabledCache("geom/move-a.png", 15, 15));
        this.check_zoom_button.setIcon(SwingUtil.loadIconEnabledCache("geom/zoom-b.png", 15, 15));
        this.check_rotate_button.setIcon(SwingUtil.loadIconEnabledCache("geom/crop_rotate-b.png", 15, 15));

        this.root_scroll_panel.getVerticalScrollBar().setUnitIncrement(10);
        this.root_scroll_panel.getHorizontalScrollBar().setUnitIncrement(10);
        this.root_scroll_panel.setViewportView(this.canvas);
        this.root_scroll_panel.setEnabled(false);
    }

    private void canvasMouseReleased() {
        List<PolygonComponent<?>> selectList = this.canvas.getSelectList();
        if (selectList != null && selectList.size() > 0) {
            selectList.forEach(e -> {
                java.awt.Point location = e.getLocation();
                java.awt.Point lastPoint = e.getLastPoint();
                if (location.x == lastPoint.x && location.y == lastPoint.y) {
                    return;
                }
                e.setLastPoint(location);
                shapeSpace.move(e.getSrc().getId(), location.x, location.y);
            });
        }
        showErrorBorder();
    }

    private void showPoint() {
        List<PolygonComponent<?>> selectList = canvas.getSelectList();
        int size = selectList.size();

        x_input.setEnabled(size > 0);
        y_input.setEnabled(size > 0);
        angle_input.setEnabled(size > 0);

        if (selectList.size() == 1) {
            PolygonComponent<?> polygonComponent = selectList.get(0);
            Integer id = polygonComponent.getSrc().getId();
            Node node = shapeSpace.findNode(id);
            double x = node.getX();
            double y = node.getY();
            double width = node.getWidth();
            double height = node.getHeight();
            int nPoints = node.getPolygon().getNpoints();

            if (unitOverload.getSelectedItem() instanceof String) {
                x_input.setText(String.format("%.2f", parseUnity(x)));
                y_input.setText(String.format("%.2f", parseUnity(y)));
                node_x_text.setText(String.format("%.2f", parseUnity(x)));
                node_y_text.setText(String.format("%.2f", parseUnity(y)));
                node_width_text.setText(String.format("%.2f", parseUnity(width)));
                node_height_text.setText(String.format("%.2f", parseUnity(height)));
                angle_input.setText(node.getAngle() == null ? "0" : String.valueOf(node.getAngle()));
                node_point_text.setText(String.valueOf(nPoints));
                id_text.setText(String.valueOf(node.getId()));
                if (StringUtils.isNotEmpty(node.getAttachedInformation())) {
                    if (node.getAttachedInformation().length() > 23) {
                        String attachedInformation = node.getAttachedInformation();
                        other_message_text.setText(String.format("%s...", attachedInformation.substring(0, 20)));
                        other_message_text.setToolTipText(attachedInformation);
                    } else {
                        other_message_text.setText(node.getAttachedInformation());
                    }
                } else {
                    other_message_text.setText("");
                }
            }
        }
        if (selectList.size() > 1) {
            x_input.setText("0");
            y_input.setText("0");
            angle_input.setText("0");
            node_x_text.setText("");
            node_y_text.setText("");
            node_width_text.setText("");
            node_point_text.setText("");
            node_height_text.setText("");
            id_text.setText("");
            other_message_text.setText("");
        }
        if (selectList.size() == 2) {

            Polygon p1 = shapeSpace.findNode(selectList.get(0).getSrc().getId()).getPolygon();
            Polygon p2 = shapeSpace.findNode(selectList.get(1).getSrc().getId()).getPolygon();
            // double similarity = PointUtil.areaSimilarity(p1, p2) / 100;
            double similarity = p1.similarity2(p2);
            // double similarity = .similarity(, 15.0D);
            similarity_text.setText(String.format("%.2f", similarity * 100));
        } else {
            similarity_text.setText("");
        }
    }

    private void showErrorBorder() {
        canvas.closeErrorBorder();
        List<T> ts = shapeSpace.collideAll();
        for (T t : ts) {
            canvas.showErrorBorder(t.getId());
        }
    }

    public void rotate(Integer id, double angle) {
        shapeSpace.rotate(id, angle);
        canvas.rotateElement(id, angle);
    }

    public void addElement(T node) {
        if (node == null) {
            throw new IllegalArgumentException();
        }

        if (node.getId() == null) {
            throw new IllegalArgumentException("node.getId() is null");
        }

        shapeSpace.add(node, false);

        T myNode = shapeSpace.myFindNode(node.getId());

        this.polygonMap.put(node.getId(), myNode);
        this.pointMap.put(node.getId(), new Point(myNode.getX(), myNode.getY()));

        PolygonComponent<T> tPolygonComponent = new PolygonComponent<>(myNode);
        this.canvas.addElement(tPolygonComponent);

        Point point = this.pointMap.get(node.getId());
        tPolygonComponent.setBounds(point.getXasInt(), point.getYasInt(), tPolygonComponent.getW(), tPolygonComponent.getH());
        tPolygonComponent.setLastPoint(point.toAwtPoint());

        tPolygonComponent.addSelectListener(new PolygonComponent.SelectListener() {
            @Override
            public void select() {
                selectElement();
            }

            @Override
            public void unselect() {
                unselectElement();
            }
        });

        re_layout_button.setEnabled(true);
    }

    public T getElement(Integer id) {
        return shapeSpace.findNode(id);
    }

    public int collideAll() {
        return shapeSpace.collideAll().size();
    }

    public void selectElement() {
    }

    public void unselectElement() {
    }

    public static RotatedRect getRect() {
        RotatedRect rotatedRect = new RotatedRect();
        rotatedRect.setCenter(new Point(6620, 1320));
        rotatedRect.setSize(new Size(142, 142));
        rotatedRect.setAngle(205);
        return rotatedRect;
    }

    public static void show(Polygon... polygons) {
        PolygonOffsetEditing<Node> polygonPolygonOffsetEditing = null;
        try {
            polygonPolygonOffsetEditing = openWindow();

            for (int i = 0; i < polygons.length; i++) {
                Polygon clone = polygons[i].clone();
                Node node = new Node(clone, 0.0D);
                node.setId(i);
                polygonPolygonOffsetEditing.addElement(node);
            }
        } finally {
            IOUtil.close(polygonPolygonOffsetEditing);
        }
    }

    public static void show(Node... nodes) {
        PolygonOffsetEditing<Node> polygonPolygonOffsetEditing = null;
        try {
            polygonPolygonOffsetEditing = openWindow();
            for (Node node : nodes) {
                polygonPolygonOffsetEditing.addElement(node);
            }
        } finally {
            IOUtil.close(polygonPolygonOffsetEditing);
        }
    }

    public static void show(ShapeSpace<Node> shapeSpace) {
        List<Node> nodes = shapeSpace.getNodes();
        Node[] nodes1 = nodes.toArray(new Node[0]);
        show(nodes1);
    }

    public static PolygonOffsetEditing<Node> openWindow() {
        PolygonOffsetEditing<Node> polygonPolygonOffsetEditing = new PolygonOffsetEditing<>(10000, 100000);

        JFrame jFrame = new JFrame();
        jFrame.setContentPane(polygonPolygonOffsetEditing);
        jFrame.setPreferredSize(new Dimension(1600, 900));
        jFrame.pack();
        SwingUtil.toCenter(jFrame);
        jFrame.setVisible(true);
        return polygonPolygonOffsetEditing;
    }

    public static Polygon test(Collection<Polygon> polygons, RotatedRect rect, double length) {

        RotatedRect.ExtendedLine extendedLine = rect.extendedLine(length);

        Polygon minPolygon = null;
        Double min = null;

        a:
        for (Polygon polygon : polygons) {
            List<Point> crossPoints = new ArrayList<>();
            for (LineSegment line : extendedLine.getLines()) {
                List<Point> crossPoint = polygon.getCrossPoint(line);
                if (crossPoint.size() == 0) {
                    continue a;
                }
                crossPoints.addAll(crossPoint);
            }
            for (Point crossPoint : crossPoints) {
                double dis = PointUtil.dis(crossPoint, rect.getCenter());
                if (min == null || dis < min) {
                    min = dis;
                    minPolygon = polygon;
                }
            }
        }

        return minPolygon;
    }

    public static void main(String[] args) throws Exception {

        ImageUtil.setupCvCore();
        PolygonOffsetEditing<Node> polygonPolygonOffsetEditing = openWindow();

        polygonPolygonOffsetEditing.addCopyListener(new CopyListener<Node>() {
            @Override
            public void copy(List<Node> copyAll) {
                String s = JSONObject.toJSONString(copyAll.stream().map(e -> {
                    JSONObject jsonObject = e.toJsonObject();
                    jsonObject.remove("swellPolygon");
                    return jsonObject;
                }).collect(Collectors.toList()));

                Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                Transferable tText = new StringSelection(s);
                clipboard.setContents(tText, null);
            }

            @Override
            public void paste() {

                Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

                try {
                    String data = (String) clipboard.getData(DataFlavor.stringFlavor);

                    JSONArray objects = JSONObject.parseArray(data);
                    List<JSONObject> jsonObjects = objects.toJavaList(JSONObject.class);
                    List<Node> version1 = jsonObjects.stream().filter(e -> {
                        Integer version = e.getInteger("version");
                        if (version == null) {
                            return false;
                        }
                        return Node.minVersion() <= version;
                    }).map(e -> e.toJavaObject(Node.class)).collect(Collectors.toList());

                    System.out.println(version1.size());

                } catch (Exception ignored) {
                }
            }
        });

        double marge_px = 100;

        Mat mat = Imgcodecs.imread("C:\\Users\\18790\\Downloads\\KT15772A03-3T29-S.jpg");
        List<Polygon> polygon1 = ImageUtil.getPolygon(mat,
                                                      new Scalar(0, 0, 0),
                                                      new Scalar(245, 245, 245),
                                                      Imgproc.RETR_EXTERNAL,
                                                      Imgproc.CHAIN_APPROX_TC89_KCOS);

        for (int i = 0; i < polygon1.size(); i++) {
            Polygon polygon = PointUtil.approxPolyDp(polygon1.get(i), 1);
            Node node = new Node(polygon, 10);
            node.setId(i);
            polygonPolygonOffsetEditing.addElement(node);
        }
    }

    private static void load1(PolygonOffsetEditing<Node> polygonPolygonOffsetEditing) {
        Mat mat = Imgcodecs.imread("D:\\Documents\\Downloads\\M.png");
        // Mat mat2 = Imgcodecs.imread("D:\\Documents\\Downloads\\ZH18055-B810-S@__.jpg");

        List<Polygon> polygon1 = ImageUtil.getPolygon(mat, new Scalar(0, 0, 0), new Scalar(245, 245, 245), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_KCOS);
        // List<Polygon> polygon2 = ImageUtil.getPolygon(mat2, new Scalar(0, 0, 0), new Scalar(100, 100, 100), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_KCOS);

        RotatedRect rect = getRect();
        for (int i = 0; i < polygon1.size(); i++) {
            polygon1.set(i, PointUtil.approxPolyDp(polygon1.get(i), 3));
            Polygon polygon2 = polygon1.get(i);
            if (!PointUtil.clockwise(polygon2)) {
                polygon1.set(i, PointUtil.reversal(polygon2));
            }
            Polygon polygon = polygon1.get(i);

            Node node = new Node(polygon, 24);
            node.setId(i);
            node.setAttachedInformation(polygon.getId());
            polygonPolygonOffsetEditing.addElement(node);
        }

        double v = CommonUtil.mmToPx(200, 120);
        Polygon test = test(polygon1, rect, v);
        if (test == null) {
            System.err.println("无法找到对应子裁片");
            return;
        }

        Polygon compose = PointUtil.compose(test, rect, 1);
        Node node = new Node(compose, 24);
        node.setId(999);
        polygonPolygonOffsetEditing.addElement(node);
    }

    @Override
    public void close() {
        if (watch != null) {
            watch.stop();
        }
    }

    static class CompositeRect {
        int x01;
        int y01;
        int x02;
        int y02;
    }

    static class Watch extends WatchThread {
        private final PolygonOffsetEditing<?> polygonOffsetEditing;

        public Watch(PolygonOffsetEditing<?> polygonOffsetEditing) throws IllegalArgumentException {
            super(70, UUID.randomUUID().toString());
            this.polygonOffsetEditing = polygonOffsetEditing;
        }

        @Override
        protected void execute() throws Exception {

            if (!polygonOffsetEditing.canvas.isFocusOwner()) {
                return;
            }

            List<PolygonComponent<?>> selectList = polygonOffsetEditing.canvas.getSelectList();
            int size = selectList.size();

            polygonOffsetEditing.auto_move_button.setEnabled(size > 0);
            polygonOffsetEditing.showPoint();
        }
    }

    public interface CopyListener<T extends Node> {
        void copy(List<T> copyAll);

        void paste();
    }

    {
        // GUI initializer generated by IntelliJ IDEA GUI Designer
        // >>> IMPORTANT!! <<<
        // DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        content_pane = new JPanel();
        content_pane.setLayout(new BorderLayout(0, 0));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new BorderLayout(0, 0));
        panel1.setPreferredSize(new Dimension(250, 24));
        content_pane.add(panel1, BorderLayout.EAST);
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new CardLayout(0, 0));
        panel1.add(panel2, BorderLayout.CENTER);
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new GridLayoutManager(7, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel2.add(panel3, "Card1");
        final JPanel panel4 = new JPanel();
        panel4.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel3.add(panel4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        auto_move_button = new JButton();
        auto_move_button.setEnabled(false);
        auto_move_button.setText("自动对齐");
        panel4.add(auto_move_button, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        re_layout_button = new JButton();
        re_layout_button.setEnabled(false);
        re_layout_button.setText("重新排列");
        panel4.add(re_layout_button, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
        final JToolBar toolBar1 = new JToolBar();
        panel4.add(toolBar1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        enable_cavity_check_box = new JCheckBox();
        enable_cavity_check_box.setText("包括空腔");
        toolBar1.add(enable_cavity_check_box);
        reset_point_check_box = new JCheckBox();
        reset_point_check_box.setText("坐标重置");
        toolBar1.add(reset_point_check_box);
        final JToolBar toolBar2 = new JToolBar();
        panel4.add(toolBar2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        auto_layout_button = new JButton();
        auto_layout_button.setText("自动布局");
        toolBar2.add(auto_layout_button);
        auto_layout_config_button = new JButton();
        auto_layout_config_button.setText("");
        toolBar2.add(auto_layout_config_button);
        final JPanel panel5 = new JPanel();
        panel5.setLayout(new BorderLayout(0, 0));
        panel3.add(panel5, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(-1, 20), new Dimension(-1, 20), new Dimension(-1, 20), 0, false));
        final JPanel panel6 = new JPanel();
        panel6.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel3.add(panel6, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JPanel panel7 = new JPanel();
        panel7.setLayout(new GridLayoutManager(5, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel6.add(panel7, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JToolBar toolBar3 = new JToolBar();
        panel7.add(toolBar3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label1 = new JLabel();
        label1.setText(" X   ");
        toolBar3.add(label1);
        x_input = new JTextField();
        x_input.setEditable(true);
        x_input.setEnabled(false);
        toolBar3.add(x_input);
        final JToolBar toolBar4 = new JToolBar();
        panel7.add(toolBar4, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label2 = new JLabel();
        label2.setText(" Y   ");
        toolBar4.add(label2);
        y_input = new JTextField();
        y_input.setEditable(true);
        y_input.setEnabled(false);
        toolBar4.add(y_input);
        final JToolBar toolBar5 = new JToolBar();
        panel7.add(toolBar5, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label3 = new JLabel();
        label3.setText(" 单位    ");
        toolBar5.add(label3);
        unitOverload = new JComboBox();
        toolBar5.add(unitOverload);
        final JToolBar toolBar6 = new JToolBar();
        panel7.add(toolBar6, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label4 = new JLabel();
        label4.setText("角度 ");
        toolBar6.add(label4);
        angle_input = new JTextField();
        angle_input.setEnabled(false);
        toolBar6.add(angle_input);
        final JPanel panel8 = new JPanel();
        panel8.setLayout(new BorderLayout(0, 0));
        panel3.add(panel8, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(-1, 20), new Dimension(-1, 20), new Dimension(-1, 20), 0, false));
        final JPanel panel9 = new JPanel();
        panel9.setLayout(new BorderLayout(0, 0));
        panel3.add(panel9, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
        final JPanel panel10 = new JPanel();
        panel10.setLayout(new BorderLayout(0, 0));
        panel10.setPreferredSize(new Dimension(10, 0));
        panel9.add(panel10, BorderLayout.WEST);
        final JPanel panel11 = new JPanel();
        panel11.setLayout(new BorderLayout(0, 0));
        panel11.setPreferredSize(new Dimension(10, 0));
        panel9.add(panel11, BorderLayout.EAST);
        final JPanel panel12 = new JPanel();
        panel12.setLayout(new GridLayoutManager(8, 1, new Insets(0, 0, 0, 0), -1, -1));
        panel9.add(panel12, BorderLayout.CENTER);
        final JToolBar toolBar7 = new JToolBar();
        panel12.add(toolBar7, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label5 = new JLabel();
        label5.setText("x");
        toolBar7.add(label5);
        final JLabel label6 = new JLabel();
        label6.setText("   ");
        toolBar7.add(label6);
        node_x_text = new JLabel();
        node_x_text.setText("");
        toolBar7.add(node_x_text);
        final JToolBar toolBar8 = new JToolBar();
        panel12.add(toolBar8, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label7 = new JLabel();
        label7.setText("y");
        toolBar8.add(label7);
        final JLabel label8 = new JLabel();
        label8.setText("   ");
        toolBar8.add(label8);
        node_y_text = new JLabel();
        node_y_text.setText("");
        toolBar8.add(node_y_text);
        final JToolBar toolBar9 = new JToolBar();
        panel12.add(toolBar9, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label9 = new JLabel();
        label9.setText("width");
        toolBar9.add(label9);
        final JLabel label10 = new JLabel();
        label10.setText("   ");
        toolBar9.add(label10);
        node_width_text = new JLabel();
        node_width_text.setText("");
        toolBar9.add(node_width_text);
        final JToolBar toolBar10 = new JToolBar();
        panel12.add(toolBar10, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label11 = new JLabel();
        label11.setText("height");
        toolBar10.add(label11);
        final JLabel label12 = new JLabel();
        label12.setText("   ");
        toolBar10.add(label12);
        node_height_text = new JLabel();
        node_height_text.setText("");
        toolBar10.add(node_height_text);
        final JToolBar toolBar11 = new JToolBar();
        panel12.add(toolBar11, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label13 = new JLabel();
        label13.setText("point");
        toolBar11.add(label13);
        final JLabel label14 = new JLabel();
        label14.setText("   ");
        toolBar11.add(label14);
        node_point_text = new JLabel();
        node_point_text.setText("");
        toolBar11.add(node_point_text);
        final JToolBar toolBar12 = new JToolBar();
        panel12.add(toolBar12, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label15 = new JLabel();
        label15.setText("id");
        toolBar12.add(label15);
        final JLabel label16 = new JLabel();
        label16.setText("   ");
        toolBar12.add(label16);
        id_text = new JLabel();
        id_text.setText("");
        toolBar12.add(id_text);
        final JToolBar toolBar13 = new JToolBar();
        panel12.add(toolBar13, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label17 = new JLabel();
        label17.setText("text");
        toolBar13.add(label17);
        final JLabel label18 = new JLabel();
        label18.setText("   ");
        toolBar13.add(label18);
        other_message_text = new JLabel();
        other_message_text.setText("");
        toolBar13.add(other_message_text);
        final JToolBar toolBar14 = new JToolBar();
        panel12.add(toolBar14, new GridConstraints(6, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(-1, 20), null, 0, false));
        final JLabel label19 = new JLabel();
        label19.setText("similarity");
        toolBar14.add(label19);
        final JLabel label20 = new JLabel();
        label20.setText("   ");
        toolBar14.add(label20);
        similarity_text = new JLabel();
        similarity_text.setText("");
        toolBar14.add(similarity_text);
        final Spacer spacer1 = new Spacer();
        panel3.add(spacer1, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
        final JPanel panel13 = new JPanel();
        panel13.setLayout(new BorderLayout(0, 0));
        content_pane.add(panel13, BorderLayout.CENTER);
        final JPanel panel14 = new JPanel();
        panel14.setLayout(new BorderLayout(0, 0));
        panel14.setPreferredSize(new Dimension(0, 25));
        panel13.add(panel14, BorderLayout.SOUTH);
        final JPanel panel15 = new JPanel();
        panel15.setLayout(new BorderLayout(0, 0));
        panel13.add(panel15, BorderLayout.CENTER);
        root_scroll_panel = new JScrollPane();
        panel15.add(root_scroll_panel, BorderLayout.CENTER);
        final JPanel panel16 = new JPanel();
        panel16.setLayout(new BorderLayout(0, 0));
        panel16.setPreferredSize(new Dimension(0, 30));
        content_pane.add(panel16, BorderLayout.NORTH);
        final JToolBar toolBar15 = new JToolBar();
        panel16.add(toolBar15, BorderLayout.WEST);
        check_select_button = new JButton();
        check_select_button.setText("");
        toolBar15.add(check_select_button);
        check_move_button = new JButton();
        check_move_button.setText("");
        toolBar15.add(check_move_button);
        check_zoom_button = new JButton();
        check_zoom_button.setText("");
        toolBar15.add(check_zoom_button);
        check_rotate_button = new JButton();
        check_rotate_button.setText("");
        toolBar15.add(check_rotate_button);
    }

    /** @noinspection ALL */
    public JComponent $$$getRootComponent$$$() {
        return content_pane;
    }

}
